classdef ShapeEditorGUI < handle
    properties (Access = private)
        % Main window
        Figure
        
        % Menus
        FileMenu
        EditMenu
        ViewMenu
        
        % Main components
        MainAxis          % 主绘图区域
        CommandPanel      % 命令面板
        EditStatusPanel   % 编辑状态面板
        
        % Controls
        BasisShapeList    % 基础形状列表
        TargetShapeList   % 目标形状列表
        CacheShapeList    % 缓存形状列表
        
        % Checkboxes
        Boundary         % 边界复选框
        Leg             % 腿部复选框
        Segment         % 段复选框
        
        % Sliders and edits
        MajorRadiusSlider    % 主半径滑块
        MajorRadiusEdit      % 主半径编辑框
        VerticalPositionSlider % 垂直位置滑块
        VerticalPositionEdit   % 垂直位置编辑框
        MinorRadiusSlider     % 次半径滑块
        MinorRadiusEdit       % 次半径编辑框
    end
    
    methods
        function obj = ShapeEditorGUI()
            obj.createMainWindow();
            obj.createMenus();
            obj.createMainComponents();
            obj.createControls();
            obj.setupCallbacks();
        end
        
        function createMainWindow(obj)
            % Create main figure window
            obj.Figure = figure(...
                'Name', 'Shape Editor',...
                'NumberTitle', 'off',...
                'Position', [100 100 1200 800],...
                'MenuBar', 'none',...
                'ToolBar', 'none',...
                'Visible', 'on',...
                'DeleteFcn', @obj.onExit);
        end
        
        function createMenus(obj)
            % Create File menu
            obj.FileMenu = uimenu(obj.Figure, 'Label', 'File');
            uimenu(obj.FileMenu, 'Label', 'Open...', 'Callback', @obj.onOpenMenuItemClicked);
            uimenu(obj.FileMenu, 'Label', 'Print...', 'Callback', @obj.onPrintMenuItemClicked);
            uimenu(obj.FileMenu, 'Label', 'Close', 'Callback', @obj.onCloseMenuItemClicked);
            
            % Create Edit menu
            obj.EditMenu = uimenu(obj.Figure, 'Label', 'Edit');
            uimenu(obj.EditMenu, 'Label', 'Clear All', 'Callback', @obj.onClearAllClicked);
            
            % Create View menu
            obj.ViewMenu = uimenu(obj.Figure, 'Label', 'View');
            uimenu(obj.ViewMenu, 'Label', 'Zoom In', 'Callback', @obj.onZoomInClicked);
            uimenu(obj.ViewMenu, 'Label', 'Zoom Out', 'Callback', @obj.onZoomOutClicked);
        end
        
        function createMainComponents(obj)
            % Create main axis for plotting
            obj.MainAxis = axes('Parent', obj.Figure,...
                'Position', [0.1 0.1 0.6 0.8],...
                'Box', 'on');
            axis(obj.MainAxis, 'equal');
            hold(obj.MainAxis, 'on');
            
            % Create command panel
            obj.CommandPanel = uipanel('Title', 'Commands',...
                'Parent', obj.Figure,...
                'Position', [0.75 0.6 0.2 0.35]);
                
            % Create edit status panel
            obj.EditStatusPanel = uipanel('Title', 'Edit Status',...
                'Parent', obj.Figure,...
                'Position', [0.75 0.1 0.2 0.45]);
        end
        
        function createControls(obj)
            % Create lists
            obj.createLists();
            
            % Create checkboxes
            obj.createCheckboxes();
            
            % Create sliders and edits
            obj.createSlidersAndEdits();
        end
        
        function createLists(obj)
            % Create basis shape list
            obj.BasisShapeList = uicontrol('Style', 'listbox',...
                'Parent', obj.CommandPanel,...
                'Position', [10 200 180 100],...
                'String', {},...
                'Callback', @obj.onBasisShapeListChanged);
            
            % Create target shape list    
            obj.TargetShapeList = uicontrol('Style', 'listbox',...
                'Parent', obj.CommandPanel,...
                'Position', [10 100 180 100],...
                'String', {},...
                'Callback', @obj.onTargetShapeListChanged);
            
            % Create cache shape list
            obj.CacheShapeList = uicontrol('Style', 'listbox',...
                'Parent', obj.CommandPanel,...
                'Position', [10 0 180 100],...
                'String', {},...
                'Callback', @obj.onCacheShapeListChanged);
        end
        
        function createCheckboxes(obj)
            % Create boundary checkbox
            obj.Boundary = uicontrol('Style', 'checkbox',...
                'Parent', obj.EditStatusPanel,...
                'Position', [10 160 100 20],...
                'String', 'Boundary',...
                'Callback', @obj.onBoundaryChanged);
            
            % Create leg checkbox
            obj.Leg = uicontrol('Style', 'checkbox',...
                'Parent', obj.EditStatusPanel,...
                'Position', [10 130 100 20],...
                'String', 'Leg',...
                'Callback', @obj.onLegChanged);
            
            % Create segment checkbox
            obj.Segment = uicontrol('Style', 'checkbox',...
                'Parent', obj.EditStatusPanel,...
                'Position', [10 100 100 20],...
                'String', 'Segment',...
                'Callback', @obj.onSegmentChanged);
        end
        
        function createSlidersAndEdits(obj)
            % Create major radius controls
            obj.createSliderWithEdit('MajorRadius', [10 70], [0.5 3.0], 1.78);
            
            % Create vertical position controls
            obj.createSliderWithEdit('VerticalPosition', [10 40], [-2.0 2.0], 0);
            
            % Create minor radius controls
            obj.createSliderWithEdit('MinorRadius', [10 10], [0.2 1.0], 0.65);
        end
        
        function createSliderWithEdit(obj, name, position, range, default)
            % Create slider
            slider = uicontrol('Style', 'slider',...
                'Parent', obj.EditStatusPanel,...
                'Position', [position(1) position(2) 120 20],...
                'Min', range(1),...
                'Max', range(2),...
                'Value', default,...
                'Callback', @(h,e)obj.onSliderChanged(name));
            obj.([name 'Slider']) = slider;
            
            % Create edit
            edit = uicontrol('Style', 'edit',...
                'Parent', obj.EditStatusPanel,...
                'Position', [position(1)+130 position(2) 50 20],...
                'String', num2str(default),...
                'Callback', @(h,e)obj.onEditChanged(name));
            obj.([name 'Edit']) = edit;
        end
        
        function setupCallbacks(obj)
            % Setup figure callbacks
            set(obj.Figure, 'WindowButtonMotionFcn', @obj.onMouseMove);
            set(obj.Figure, 'WindowButtonDownFcn', @obj.onMouseDown);
            set(obj.Figure, 'WindowButtonUpFcn', @obj.onMouseUp);
        end
        
        % Callback methods
        function onExit(obj, ~, ~)
            delete(obj.Figure);
        end
        
        function onOpenMenuItemClicked(obj, ~, ~)
            file = uigetfile('*.fig');
            if ~isequal(file, 0)
                open(file);
            end
        end
        
        function onPrintMenuItemClicked(obj, ~, ~)
            printdlg(obj.Figure);
        end
        
        function onCloseMenuItemClicked(obj, ~, ~)
            selection = questdlg(['Close ' get(obj.Figure, 'Name') '?'],...
                ['Close ' get(obj.Figure, 'Name') '...'],...
                'Yes','No','Yes');
            if strcmp(selection, 'No')
                return;
            end
            delete(obj.Figure);
        end
        
        function onClearAllClicked(obj, ~, ~)
            cla(obj.MainAxis);
        end
        
        function onZoomInClicked(obj, ~, ~)
            zoom(obj.Figure, 'in');
        end
        
        function onZoomOutClicked(obj, ~, ~)
            zoom(obj.Figure, 'out');
        end
        
        function onBasisShapeListChanged(obj, ~, ~)
            % Handle basis shape list selection change
        end
        
        function onTargetShapeListChanged(obj, ~, ~)
            % Handle target shape list selection change
        end
        
        function onCacheShapeListChanged(obj, ~, ~)
            % Handle cache shape list selection change
        end
        
        function onBoundaryChanged(obj, ~, ~)
            if get(obj.Boundary, 'Value')
                set(obj.Leg, 'Value', 0);
                set(obj.Segment, 'Value', 0);
            end
        end
        
        function onLegChanged(obj, ~, ~)
            if get(obj.Leg, 'Value')
                set(obj.Boundary, 'Value', 0);
                set(obj.Segment, 'Value', 0);
            end
        end
        
        function onSegmentChanged(obj, ~, ~)
            if get(obj.Segment, 'Value')
                set(obj.Boundary, 'Value', 0);
                set(obj.Leg, 'Value', 0);
            end
        end
        
        function onSliderChanged(obj, name)
            slider = obj.([name 'Slider']);
            edit = obj.([name 'Edit']);
            value = get(slider, 'Value');
            set(edit, 'String', num2str(value));
        end
        
        function onEditChanged(obj, name)
            slider = obj.([name 'Slider']);
            edit = obj.([name 'Edit']);
            value = str2double(get(edit, 'String'));
            
            % Validate range
            if value < get(slider, 'Min') || value > get(slider, 'Max')
                value = get(slider, 'Value');
                set(edit, 'String', num2str(value));
                return;
            end
            
            set(slider, 'Value', value);
        end
        
        function onMouseMove(obj, ~, ~)
            % Handle mouse movement
        end
        
        function onMouseDown(obj, ~, ~)
            % Handle mouse button down
        end
        
        function onMouseUp(obj, ~, ~)
            % Handle mouse button up
        end
    end
end